<?php
/**
 * crcl/base
 *
 * Copyright 2013 CRCL - André Sabosch - info@crcl.de
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * File handling, chainable
 *
 * \crcl\base\File::getInstance($sFile)->getDirectory()
 */

namespace crcl\base;

interface IFile
{
  /**
   * returns current file
   *
   * @return string
   */
  public function toString();
  public function __toString();

  /**
   * Return just directory, without filename
   *
   * @return  string
   */
  public function getDirectory();

  /**
   * Returns \TRUE if current file has extension, \FALSE if not
   *
   * @return bool
   */
  public function hasExtension();

  /**
   * Returns extension of current file
   * throws \crcl\base\file\Exception::ERROR_NOEXTENSION if no extension exists
   *
   * @return  string
   */
  public function getExtension();
}

class File extends \crcl\base\instance\Factory implements IFile
{
  public static function factory($sFile)
  {
    if (!\is_string($sFile))
    {
      throw new file\Exception(
        'No string',
        file\Exception::ERROR_NOSTRING,
        array('invalid' => $sFile, 'type' => \gettype($sFile)));
    }
    $oInstance = new File($sFile);
    return $oInstance;
  }

  public function __construct($sFile)
  {
    $sFile = $this->normalizePath($sFile);
    $this->sFile = $sFile;
  }

  public function toString()
  {
    $this->sFile = (string)$this->sFile;
    return $this->sFile;
  }

  public function __toString()
  {
    return $this->toString();
  }

  public function getDirectory()
  {
    $sDirectory = $this->sFile;
    //error in php...
    $iLength = \strlen($sDirectory);
    if ($iLength > 0)
    {
      if ($sDirectory[$iLength-1] != '/')
      {
        $sDirectory = \pathinfo($sDirectory, \PATHINFO_DIRNAME);
      }
    }
    $sDirectory = $this->normalizePath($sDirectory);
    $sDirectory = String::getInstance($sDirectory)->doEndWith('/')->toString();
    return $sDirectory;
  }

  public function hasExtension()
  {
    $bResult = \FALSE;
    $iPosDot = \strrpos($this->sFile, '.');
    if ($iPosDot !== \FALSE)
    {
      $iPosSlash = \strrpos($this->sFile, '/');
      if ($iPosSlash !== \FALSE)
      {
        if ($iPosDot > $iPosSlash)
        {
          $bResult = \TRUE;
        }
      }
      else
      {
        //we have a ".", but no "/". There must be an extension
        $bResult = \TRUE;
      }
    }
    return $bResult;
  }

  public function getExtension()
  {
    if (!$this->hasExtension())
    {
      throw new file\Exception(
        'No extension',
        file\Exception::ERROR_NOEXTENSION,
        array('file' => $this->sFile));
    }
    $sExtension = \strrchr($this->sFile, '.');
    $sExtension = String::getInstance($sExtension)->doNotStartWith('.')->toString();
    return $sExtension;
  }

  /** PRIVATE *************************************************************************************/

  private $sFile;

  private function normalizePath($sPath)
  {
    //lets   path win style pathes on linux too
    $sPath = \str_replace('\\', '/', $sPath);
    return $sPath;
  }
}